use std::sync::{Arc, Mutex};

use tsp::population::Population;

use tsp::{init_log, read_map};

pub fn init_matches<'a>() -> clap::ArgMatches<'a> {
    use clap::{App, Arg};
    App::new("Tsp-tester")
        .version("0.1.0")
        .about("Tsp 测试机器")
        .arg(
            Arg::with_name("debug")
                .long("debug")
                .value_name("DEBUG LEVEL")
                .help("WARN/INFO/DEBUG/TRACE")
                .default_value("WARN")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("data")
                .help("你想要计算的图")
                .index(1)
                .required(true),
        )
        .get_matches()
}

fn main() {
    let data_file;
    {
        let matches = init_matches();
        init_log(matches.value_of("debug").unwrap()).unwrap();
        data_file = String::from(matches.value_of("data").unwrap());
    }

    // TODO: 写的更像人看的
    for i in 1..=10 {
        let pc = 0.1 * i as f64;
        for j in 1..=10 {
            let pm = 0.1 * j as f64;
            for k in 1..=10 {
                let pn = 10 * k;
                let result = Arc::new(Mutex::new([0.0; 1000]));
                let mut handles: Vec<std::thread::JoinHandle<()>> = vec![];

                for _ in 0..10 {
                    let data_file = data_file.clone();
                    let result = result.clone();

                    let handle = std::thread::spawn(move || {
                        let mut population =
                            Population::new(read_map(&data_file).unwrap(), pn, pm, pc);
                        for iter_time in 0..1000 {
                            let cur_best = population.iterator();
                            let cur_best = match cur_best {
                                Some(life) => life.fitness(),
                                None => 1000 as f64,
                            };
                            result.lock().unwrap()[iter_time] += cur_best;
                            log::trace!("{}: {:?} Distance = {}", iter_time, cur_best, cur_best);
                        }
                    });

                    handles.push(handle);
                }

                for handle in handles {
                    handle.join().unwrap();
                }

                for iter_time in 0..1000 {
                    result.lock().unwrap()[iter_time] /= 10.0;
                    println!(
                        "{},{},{},{},{}",
                        pc,
                        pm,
                        pn,
                        iter_time,
                        result.lock().unwrap()[iter_time]
                    );
                }
                log::info!("pc = {}, pm ={}, pn {} Done!", pc, pm, pn);
            }
        }
    }
}
